package com.cctc.rds.scheduler.server.raft.rpc;

import com.cctc.rds.nrpc.api.rpc.RpcMethod;
import com.cctc.rds.nrpc.api.rpc.RpcServerRouter;
import com.cctc.rds.scheduler.core.raft.TaskRpc;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * Raft 集群 RPC 服务端路由（查找）器。
 */
public class TaskRpcServerRouter implements RpcServerRouter {
    private TaskRpc taskRpc;
    private Map<String, RpcMethod> rpcMethods;

    public TaskRpcServerRouter(TaskRpc taskRpc) {
        this.taskRpc = taskRpc;
        this.rpcMethods = getAllRpcMethods();
    }

    private Map<String, RpcMethod> getAllRpcMethods() {
        Map<String, RpcMethod> rpcMethods = new HashMap<>();
        Method[] methods = TaskRpc.class.getMethods();
        for (Method method : methods) {
            String rpcMethodName = getRpcMethodName(method.getName(), method.getParameterTypes());
            RpcMethod rpcMethod = new RpcMethod(taskRpc, method);
            rpcMethods.put(rpcMethodName, rpcMethod);
        }
        return rpcMethods;
    }

    private String getRpcMethodName(String methodName, Class<?>[] parameterTypes) {
        StringBuilder builder = new StringBuilder(methodName);
        if (parameterTypes != null && parameterTypes.length > 0) {
            for (Class<?> parameterType : parameterTypes) {
                builder.append("@").append(parameterType.getName());
            }
        }
        return builder.toString();
    }

    @Override
    public RpcMethod route(Class<?> interfaces, String methodName, Class<?>[] parameterTypes) throws NoSuchMethodException {
        String rpcMethodName = getRpcMethodName(methodName, parameterTypes);
        RpcMethod rpcMethod = rpcMethods.get(rpcMethodName);
        if (rpcMethod == null) {
            throw new NoSuchMethodException(rpcMethodName + " not found.");
        }
        return rpcMethod;
    }
}
